From e090e2ad78ad4f59842bacd3d06320ab17030e00 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 16 Aug 2014 15:00:38 -0700 Subject: [PATCH] Run cargo off the main thread. On windows the main thread suffers the same fate as rustdoc (as linked in the comments), and hence needs to run off the main thread for now. --- src/cargo/lib.rs | 25 ++++++++++++++++++++++--- src/cargo/sources/git/utils.rs | 20 ++++++++++++++++---- tests/test_cargo_compile_git_deps.rs | 6 +++--- 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index 0240a36f3..f701553d3 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -84,7 +84,10 @@ pub fn execute_main<'a, V: Encodable, io::IoError>>( exec: fn(T, U, &mut MultiShell) -> CliResult>, options_first: bool) { - process::(|rest, shell| call_main(exec, shell, rest, options_first)); + // see comments below + off_the_main_thread(proc() { + process::(|rest, shell| call_main(exec, shell, rest, options_first)); + }); } pub fn call_main<'a, @@ -106,8 +109,11 @@ pub fn execute_main_without_stdin<'a, V: Encodable, io::IoError>>( exec: fn(T, &mut MultiShell) -> CliResult>, options_first: bool) { - process::(|rest, shell| call_main_without_stdin(exec, shell, rest, - options_first)); + // see comments below + off_the_main_thread(proc() { + process::(|rest, shell| call_main_without_stdin(exec, shell, rest, + options_first)); + }); } pub fn call_main_without_stdin<'a, @@ -240,3 +246,16 @@ fn json_from_stdin() -> CliResult { CliError::new("Could not process standard in as input", 1) }) } + +// Seems curious to run cargo off the main thread, right? Well do I have a story +// for you. Turns out rustdoc does a similar thing, and already has a good +// explanation [1] though, so I'll just point you over there. +// +// [1]: https://github.com/rust-lang/rust/blob/85fd37f/src/librustdoc/lib.rs#L92-L122 +fn off_the_main_thread(p: proc():Send) { + let (tx, rx) = channel(); + spawn(proc() { p(); tx.send(()); }); + if rx.recv_opt().is_err() { + std::os::set_exit_status(std::rt::DEFAULT_ERROR_CODE); + } +} diff --git a/src/cargo/sources/git/utils.rs b/src/cargo/sources/git/utils.rs index 3894879e6..59a19b6ee 100644 --- a/src/cargo/sources/git/utils.rs +++ b/src/cargo/sources/git/utils.rs @@ -148,10 +148,14 @@ impl GitRemote { pub fn checkout(&self, into: &Path) -> CargoResult { let repo = if into.exists() { let r = try!(git2::Repository::open(into)); - try!(self.fetch_into(&r)); + try!(self.fetch_into(&r).chain_error(|| { + internal(format!("failed to fetch into {}", into.display())) + })); r } else { - try!(self.clone_into(into)) + try!(self.clone_into(into).chain_error(|| { + internal(format!("failed to clone into: {}", into.display())) + })) }; Ok(GitDatabase { remote: self.clone(), path: into.clone(), repo: repo }) @@ -179,6 +183,7 @@ impl GitRemote { fn clone_into(&self, dst: &Path) -> CargoResult { let url = self.url.to_string(); + try!(mkdir_recursive(dst, UserDir)); let repo = try!(git2::build::RepoBuilder::new().bare(true) .hardlinks(false) .clone(url.as_slice(), dst)); @@ -222,7 +227,10 @@ impl<'a> GitCheckout<'a> { // If the git checkout already exists, we don't need to clone it again let repo = match git2::Repository::open(into) { Ok(repo) => repo, - Err(..) => try!(GitCheckout::clone_repo(database.get_path(), into)), + Err(..) => { + try!(mkdir_recursive(&into.dir_path(), UserDir)); + try!(GitCheckout::clone_repo(database.get_path(), into)) + } }; Ok(GitCheckout { location: into.clone(), @@ -251,7 +259,11 @@ impl<'a> GitCheckout<'a> { let url = try!(source.to_url().map_err(human)); let url = url.to_string(); - let repo = try!(git2::Repository::clone(url.as_slice(), into)); + let repo = try!(git2::Repository::clone(url.as_slice(), + into).chain_error(|| { + internal(format!("failed to clone {} into {}", source.display(), + into.display())) + })); Ok(repo) } diff --git a/tests/test_cargo_compile_git_deps.rs b/tests/test_cargo_compile_git_deps.rs index 241dc2ba9..18bd5f634 100644 --- a/tests/test_cargo_compile_git_deps.rs +++ b/tests/test_cargo_compile_git_deps.rs @@ -907,7 +907,7 @@ test!(dep_with_changed_submodule { .with_stdout(format!("{} git repository `[..]`\n\ {} dep1 v0.5.0 ([..])\n\ {} foo v0.5.0 ([..])\n\ - {} `target/foo`\n\ + {} `target[..]foo`\n\ project2\ ", UPDATING, @@ -919,7 +919,7 @@ test!(dep_with_changed_submodule { let mut file = File::create(&git_project.root().join(".gitmodules")); file.write_str(format!("[submodule \"src\"]\n\tpath = src\n\turl={}", - git_project3.root().display()).as_slice()); + git_project3.url()).as_slice()); git_project.process("git").args(["submodule", "sync"]).exec_with_output().assert(); git_project.process("git").args(["fetch"]).cwd(git_project.root().join("src")) @@ -942,7 +942,7 @@ test!(dep_with_changed_submodule { .with_stdout(format!("{} git repository `[..]`\n\ {} dep1 v0.5.0 ([..])\n\ {} foo v0.5.0 ([..])\n\ - {} `target/foo`\n\ + {} `target[..]foo`\n\ project3\ ", UPDATING, -- 2.30.2